
#include "kb.h"                 // keybaord event type 
#include "touch_algorithm.h"    // touch event type 
#include "custom_event.h"
#include "gui.h"                // GUI header

#include "views.h"              // include all views 
#include "log.h"                // LOG file 

#define VTLOG0      xLOG_INFO0
#define VTLOG1      xLOG_INFO1
#define VTLOG2      xLOG_INFO2


#include "xapp_clock.h"
#include "xapp_access.h"
#include "xapp_profile.h"
#include "xapp_localize.h"
#include "views_util.h"

enum tagTimer
{
    tagTimerStart = 0,
    tagTimerHourSelected,
    tagTimerMinuteSelected,
    tagTimerHourClickSelected,
    tagTimerMinuteClickSelected, 
};

enum fsmTimer
{
    fsmTimerIdle = 0,    
    fsmTimerUpdate, 
};

// declare function 
GUI_VIEW_FUNC_DECLARE_ALL;
static void local_view_event_handler( uint32_t tag );


static setup_time_st time_st={
    .textid=TEXT_TAG_SET_TIME,
    .phour=NULL,
    .pminute=NULL,
    .cb=NULL
    },*ptime_st=&time_st;

void view_enter_setup_time(const gui_view_t *parent,uint16_t textid,uint8_t *p_hour,uint8_t *p_minute,setup_time_cb_t cb)
{
    ptime_st->textid = textid;
	ptime_st->phour = p_hour;
	ptime_st->pminute = p_minute;
    if(p_hour)  ptime_st->hour   = *p_hour;
    if(p_minute)ptime_st->minute = *p_minute;
    ptime_st->parent = parent;
    ptime_st->cb = cb;
    gui_view_create_sub( parent, &viewSetTime );
}

static const uint16_t HOUR_text = 0x0048;//0x65f6;// 'H'的unicode
static const uint16_t MINUTE_text = 0x004D;//0x5206; // 'M'的unicode 
static uint8_t textbuf0[20];

#define ITEM_HEIGHT (GUI_LCD_RES_V/5)
#define PICK_HEIGHT (ITEM_HEIGHT*3)
#define Y_OFFSET    (ITEM_HEIGHT*2/3)

#define HOUR_WIDTH  (GUI_LCD_RES_H*120/240)
#define MINU_WIDTH  (GUI_LCD_RES_H*120/240)

const static ui_widgets_type_t wglTimerSelect[] = 
{
    // background 
    [0] = uiCanvas(0, 0, GUI_LCD_RES_H, GUI_LCD_RES_V, COLOR_BLACK ),

    // line 
    [1] = uiCanvas( SIZE_SCALE(30), Y_OFFSET+ITEM_HEIGHT*1-3,  GUI_LCD_RES_H - SIZE_SCALE(30) * 2, 2, COLOR_GRAY ),
    // line2 
    [2] = uiCanvas( SIZE_SCALE(30), Y_OFFSET+ITEM_HEIGHT*2-3 , GUI_LCD_RES_H - SIZE_SCALE(30) * 2, 2, COLOR_GRAY ), 

    // time set(picker) hour, center Y = (y * 2 + h ) / 2 - height / 2 h = 3 * 20 + 2 *pitch 
    [3] = uiPicker( SIZE_SCALE(0), Y_OFFSET, HOUR_WIDTH, PICK_HEIGHT, COLOR_WHITE, ALIGN_MIDDLE_CENTOR, ENCODING_ASCII, FONT_ASCII_1_28_37, ITEM_HEIGHT-37 ),
    [4] = uiPicker( HOUR_WIDTH,    Y_OFFSET, MINU_WIDTH, PICK_HEIGHT, COLOR_WHITE, ALIGN_MIDDLE_CENTOR, ENCODING_ASCII, FONT_ASCII_1_28_37, ITEM_HEIGHT-37 ), 
    // unit ( 40 * 2 + 60 ) / 2 - 20 / 2 = 60
    [5] = uiLabel( HOUR_WIDTH-20, Y_OFFSET+ITEM_HEIGHT*1, 24, 24, COLOR_BLACK, COLOR_ORANGE, ALIGN_LEFT_TOP, FILL_NONE, ENCODING_UNICODE, FONT_UNICODE_20_29, &HOUR_text, 1 ), 
    // time set(picker) minute 
    [6] = uiLabel( HOUR_WIDTH+MINU_WIDTH-20,Y_OFFSET+ITEM_HEIGHT*1, 24, 24, COLOR_BLACK, COLOR_ORANGE, ALIGN_LEFT_TOP, FILL_NONE, ENCODING_UNICODE, FONT_UNICODE_20_29, &MINUTE_text, 1 ),

    // mask color 1
    [7] = uiColorReplacer( 0, Y_OFFSET+ITEM_HEIGHT*1, GUI_LCD_RES_H, ITEM_HEIGHT, COLOR_WHITE, COLOR_ORANGE ),
    // mask color 
    //[8] = uiColorReplacer( 0, (GUI_LCD_RES_V-Y_OFFSET-10-PICK_HEIGHT)/2+ITEM_HEIGHT*1-3, GUI_LCD_RES_H, ITEM_HEIGHT, COLOR_WHITE, COLOR_ORANGE ), 
    
    //设置时间
	[8] = uiTextbox( 0, 0, GUI_LCD_RES_H/2, 0, COLOR_BLACK, COLOR_WHITE, ALIGN_MIDDLE_CENTOR,   FILL_NONE, ENCODING_UNICODE, FONT_UNICODE_20_29 ),

    //时间
	[9] = uiNumberlistWithBuffer( GUI_LCD_RES_H/3*2, 0, GUI_LCD_RES_H/3-0, 0, COLOR_BLACK, COLOR_WHITE, ALIGN_RIGHT_CENTOR, FILL_NONE, ENCODING_ASCII, FONT_ASCII_1_22_29, "%02d:%02d", textbuf0, 5 ),

    // button bg
	[10] = uiPictureBox( IMG_Exercise_Play_Stop_Button_075_075_02, 1, (GUI_LCD_RES_H-75)/2, GUI_LCD_RES_V-75, 75, 75 ),
    
    // button text -36+5 加5是因为文本被认定为高度29,但实际可见部分高度仅为20,因此文字会被往上顶,导致竖直方向不居中
	[11] = uiTextbox( 0, GUI_LCD_RES_V-12*2-36+5, GUI_LCD_RES_H, 12*2+36, COLOR_BLACK, COLOR_WHITE, ALIGN_MIDDLE_CENTOR,   FILL_NONE, ENCODING_UNICODE, FONT_UNICODE_20_29 ), 
    
    // mask color 2 same as widget[7]
    [12] = uiColorReplacer( 0, Y_OFFSET+ITEM_HEIGHT*1, GUI_LCD_RES_H, ITEM_HEIGHT, COLOR_BLACK, REAL_COLOR_GRAY ),
};

#if ITEM_HEIGHT < 37
#error "item height is too small"
#endif

const static ui_widgets_type_t wglTimerSelectTouch_Click[] =
{
    [0] = uiTouch( 0, GUI_LCD_RES_V-12*2-36, GUI_LCD_RES_H, 12*2+36, tagTimerStart ), 
    [1] = uiTouch( 0, 	       0, HOUR_WIDTH, ITEM_HEIGHT*4, tagTimerHourClickSelected ),
    [2] = uiTouch( HOUR_WIDTH, 0, MINU_WIDTH, ITEM_HEIGHT*4, tagTimerMinuteClickSelected ), 
};

const static ui_widgets_type_t wglTimerSelectTouch_Down[] =
{
    [0] = uiTouch( 0, 	       0, HOUR_WIDTH, ITEM_HEIGHT*4, tagTimerHourSelected ),
    [1] = uiTouch( HOUR_WIDTH, 0, MINU_WIDTH, ITEM_HEIGHT*4, tagTimerMinuteSelected ), 
};

GUI_VIEW_DEF( viewSetTime ) = 
{
    // name 
    .name = "Settings+time",
    
    // init 
    .init = initialize,
    .display_func = display_callback_func,
    .refresh_func_check = display_refresh_func,
    .destroy_func = on_destroy_func,
    .set_parent_func = on_set_parent_func, 
    
    // input 
    .on_touch = on_touch,
    .on_button = on_button,
    .on_event_update = on_event_update,     
    
    .pWidgetlist =  (ui_widgets_type_t*)wglTimerSelect /* 3. fill with widgets list name */,
    .widget_cnt = WIDGET_COUNT( wglTimerSelect ), /* 3. fill with widgets list name */

    .flag = GUI_VIEW_FLAG_FUNC
};


#define INC_STEP        (10)
#define INC_OFFSET      (20)
#define DEC_OFFSET      (-20)

#define FLING_DISABLE           0
#define FLING_HOUR_ENABLED      1
#define FLING_MINUTE_ENABLED    2 

//static int16_t m_data_offset = 0;

//static int16_t m_hour_delta_y;
//static int16_t m_minute_delta_y; 

static uint8_t m_timer_fling_flags = 0;

static gui_fling_t *m_hour_fling; 
static gui_fling_t *m_minute_fling;
static uint8_t hour_selected_index = 0;
static uint8_t minute_selected_index = 0;
//static int16_t roll_last_total;

static void initialize(gui_menu_t * menu, void* pvParameter)
{
//    uint8_t hour = xapp_clock_get_now()->hour;
//    uint8_t minute = xapp_clock_get_now()->minute;
//    ui_widgets_type_t * widgets = menu->widgets;
	
    menu->interval = 0;
    const profile_system_t* p_profile_system = xapp_profile_get_system();
    menu->lifetime = p_profile_system->time_of_light_on * 1000;

//    m_hour_delta_y = -(ITEM_HEIGHT)*hour;
//    m_minute_delta_y = -(ITEM_HEIGHT)*minute; // item height * 1, 设置一个有个值
    hour_selected_index = ptime_st->hour;
    minute_selected_index = ptime_st->minute; // 最小有效值1分钟

    m_timer_fling_flags = 0;

    // 初始化
    m_hour_fling   = gui_fling_get();
    m_minute_fling = gui_fling_get();
    
    gui_fling_init_t init_obj = GUI_FLING_CONFIG( 0  , Y_OFFSET, HOUR_WIDTH, PICK_HEIGHT, true,  0, 0, ITEM_HEIGHT, 50, m_minute_fling );
    gui_fling_init( m_hour_fling, &init_obj );
    
    gui_fling_init_t init_obj1 = GUI_FLING_CONFIG( 160, Y_OFFSET, MINU_WIDTH, PICK_HEIGHT, false, 0, 0, ITEM_HEIGHT, 50, NULL );
    gui_fling_init( m_minute_fling, &init_obj1 );
    
    m_hour_fling->roll_offset_total = -hour_selected_index * ITEM_HEIGHT;
    m_minute_fling->roll_offset_total = -minute_selected_index * ITEM_HEIGHT;
}
static void on_set_parent_func(gui_menu_t * menu, const gui_view_t * parent)
{
    p_this_parent = parent;
}
/* 销毁函数
// 在销毁前处理当前信息，比如不允许销毁时，将当前界面状态保存为background。
// true:  允许销毁
// false: 不允许自动销毁，则GUI只关闭当前显示，输入事件仍由当前view进行处理。
          那么view判断当前状态为background时，作出对应background下的按键、触摸等事件反馈
*/
static uint32_t on_destroy_func(gui_menu_t * menu)
{
//    roll_last_total = m_hour_fling.roll_offset_total;

    gui_fling_set_disable( m_hour_fling );     
    return GUI_DESTROY_RET_DEFAULT; 
}

static void display_callback_func(gui_menu_t * menu)
{
    ui_property_t prop;
    ui_widgets_type_t * widgets = menu->widgets;
    string_t const *s;
    
    widgets[1].visible = widgets[2].visible = 0;
    
    if( menu->source == GUI_VIEW_REQ_SRC_UPDATE_FLING || IS_REQ_SRC_CREATE( menu->source))
    {
    // 小时的选项
    PROP_ASSIGN_PICKER_OFFS(prop,gui_assets_get_hour_items,24,m_hour_fling->roll_offset_total);
    PROP_UPDATE_AT_NO( 3 );
    // 获取设置的index
    hour_selected_index = widgets[3].uiPicker.extension->picker.index;

    // 松开的时候，强制将picker的delta_y置为0，这样中间数字居中
    PROP_ASSIGN_PICKER_OFFS(prop,gui_assets_get_minute_items,60,m_minute_fling->roll_offset_total);
    PROP_UPDATE_AT_NO( 4 );
    // 获取设置的index
    minute_selected_index = widgets[4].uiPicker.extension->picker.index;
    
    VTLOG2("settime  index:hour = %d, minute = %d", widgets[3].uiPicker.extension->picker.index,  widgets[4].uiPicker.extension->picker.index);
    }

    if(IS_REQ_SRC_CREATE( menu->source))
    {
    // 小时单位
    PROP_UPDATE_NULL_AT_NO(5);

    // 分钟单位
    PROP_UPDATE_NULL_AT_NO(6);
    
    widgets[5].visible = widgets[6].visible = 0;

    //时间设置
    s = xapp_local_text_item_get( ptime_st->textid );
    PROP_ASSIGN_TEXT( prop, s->text, s->len );
    PROP_UPDATE_AT_NO( 8 );

    //时间
	{
    uint8_t h = xapp_clock_get_now()->hour;
    uint8_t m = xapp_clock_get_now()->minute;
    if( h > 12 && profile_sys_get_time_format())
      h -= 12;
    prop.numberlist.value[0] = h;
    prop.numberlist.value[1] = m;
    prop.numberlist.cnt = 2;
    PROP_UPDATE_AT_NO( 9 );
	}
    
    //保存
    s = xapp_local_text_item_get( TEXT_TAG_WEEKDAY_SIMP_SUNDAY );
    PROP_ASSIGN_TEXT( prop, s->text, s->len );
    PROP_UPDATE_AT_NO( 11 );
    widgets[11].visible = 0;
    }
}


static int display_refresh_func(gui_menu_t * menu)
{
    // 永远允许刷新
    return 1;
}

static void on_touch(void* pvParameters, gui_menu_t * menu)
{
    tp_algo_evt_t* touch = (tp_algo_evt_t*)pvParameters;
    gui_core_lifetime_refresh( menu );
    switch( touch->type ) 
    {
        case TP_ALGO_EVT_TYPE_DOWN:
            VTLOG0("touch press");
        // 检测触摸按下的位置，判断哪个哪个picker需要拖动
        if( !GUI_WIDGET_LIST_CHECK_TOUCH( wglTimerSelectTouch_Down, WIDGET_COUNT(wglTimerSelectTouch_Down), 0, 0, touch->x, touch->y, local_view_event_handler) )
        {
            m_timer_fling_flags = FLING_DISABLE;
        }
        break;

        case TP_ALGO_EVT_TYPE_UP:
            VTLOG1("touch release: flag = %d", m_timer_fling_flags);
        // 触摸松开，先滚动补偿（由于先产生UP事件再产生滑动事件，这里的补偿会被后续的滑动事件替换掉）
        // 这里必须要执行，不然松开时无法滚动到适应的位置）
        if( m_timer_fling_flags == FLING_HOUR_ENABLED )
        {
            gui_fling_on_touch_release( m_hour_fling );
        }
        else if( m_timer_fling_flags == FLING_MINUTE_ENABLED )
        {
            gui_fling_on_touch_release( m_minute_fling ); 
        }
        else 
        {

        }
        break;

        case TP_ALGO_EVT_TYPE_CLICK:  
        if( GUI_WIDGET_LIST_CHECK_TOUCH( wglTimerSelectTouch_Click, WIDGET_COUNT(wglTimerSelectTouch_Click), 0, 0, touch->x, touch->y, local_view_event_handler) )
        {

        }
        break;

//        case TP_ALGO_EVT_TYPE_HOLD:
//        if(/* !drag_from_top && */touch->deltaY != 0 ) // 需要添加按下时是否在滚动区域中
//        {
//            if( m_timer_fling_flags == FLING_HOUR_ENABLED) // 小时滚动
//            {
//                gui_fling_set_roll( m_hour_fling, touch->deltaY );
//            }
//            else if( m_timer_fling_flags == FLING_MINUTE_ENABLED ) // 分钟滚动
//            {
//                gui_fling_set_roll( m_minute_fling, touch->deltaY );
//            }
//            else
//            {
//                // nothings to fling
//            }
//        }
//        break;

        // should wait for fling end
        case TP_ALGO_EVT_TYPE_SLIDE_R:
        {
//            if( p_this_parent != NULL )
//            {
//                gui_view_create_return( p_this_parent );
//                p_this_parent = NULL;
//            }
//            else 
//            {
                gui_view_create_return( &viewAppsList );
//            }
            gui_fling_set_disable( m_hour_fling );
        }
        break;

        case TP_ALGO_EVT_TYPE_SLIDE_U:
            VTLOG1("touch slide to UP, flag = %d", m_timer_fling_flags );
        if( m_timer_fling_flags == FLING_HOUR_ENABLED) // 小时滚动
        {
            gui_fling_switch_item( m_hour_fling, 1, true );
        }
        else if( m_timer_fling_flags == FLING_MINUTE_ENABLED ) // 分钟滚动
        {
            gui_fling_switch_item( m_minute_fling, 1, true );
        }
        else 
        {
            // nothings to fling 
        }
        break;

        case TP_ALGO_EVT_TYPE_SLIDE_D:
            VTLOG1("touch slide to DOWN, flag = %d", m_timer_fling_flags );
        if( m_timer_fling_flags == FLING_HOUR_ENABLED) // 小时滚动
        {
            gui_fling_switch_item( m_hour_fling, 1, false );
        }
        else if( m_timer_fling_flags == FLING_MINUTE_ENABLED ) // 分钟滚动
        {
            gui_fling_switch_item( m_minute_fling, 1, false );
        }
        else 
        {
            // nothings to fling 
        }
        break;

        
        default:
            break; 
    }
}

#ifdef BOARD_IQ120
static void on_button(void* pvParameters, gui_menu_t * menu)
{
    kb_evt_t * kb = (kb_evt_t*)pvParameters;
    
    switch( kb->type ) 
    {
        case KB_EVT_CLICK:
        if( kb->idx == 0 || kb->idx == 1 )
        {
            if( p_this_parent != NULL )
            {
                gui_view_create_return( p_this_parent );
                p_this_parent = NULL;
            }
            else 
            {
                gui_view_create( &viewAppsList );
            }
        }
        else if( kb->idx == 2 )
        {
            gui_view_create( &viewWatchface );
        }
            break; 
        default:
            break;
    }
 
}
#else 
static void on_button(void* pvParameters, gui_menu_t * menu)
{
    kb_evt_t * kb = (kb_evt_t*)pvParameters;
    
    switch( kb->type ) 
    {
        case KB_EVT_CLICK:
        if( p_this_parent != NULL )
        {
            gui_view_create_return( p_this_parent );
            p_this_parent = NULL;
        }
        else 
        {
            gui_view_create_return( &viewAppsList );
        }
            break; 
        default:
            break;
    }
 
}
#endif 

static void on_event_update(void * pvParameters, gui_menu_t * menu)
{
    // nothings to do 
}

static void local_view_event_handler(uint32_t tag )
{
    switch( tag ) 
    {
        case tagTimerStart:
        
        //更新时间
        if(ptime_st->cb)
        {
            ptime_st->cb(hour_selected_index, minute_selected_index);
            ptime_st->cb = NULL;
        }
        
        //获得小时
        if(ptime_st->phour)
        {
            *ptime_st->phour = hour_selected_index;
            ptime_st->phour = NULL;
        }
        
        //获得分钟
        if(ptime_st->pminute)
        {
            *ptime_st->pminute = minute_selected_index;
            ptime_st->pminute = NULL;
        }
        
		//接着往下执行,不break;
		
        //case tagTimerCancel:
        // 创建界面
        if( p_this_parent != NULL )
        {
            gui_view_create_return( p_this_parent );
            p_this_parent = NULL;
        }
        else 
        {
            gui_view_create_return( views_load_current_watchface() );
        }
        gui_fling_set_disable( m_hour_fling );
        break;

        case tagTimerHourSelected:
        // hold active on HOUR        
        m_timer_fling_flags = FLING_HOUR_ENABLED;
        gui_fling_on_touch_press( m_hour_fling ); 
        VTLOG0("select hour");
        break;

        case tagTimerMinuteSelected:
        // hold active on MINUTE
        m_timer_fling_flags = FLING_MINUTE_ENABLED;
        gui_fling_on_touch_press( m_minute_fling );
        VTLOG0("select minute");
        break;        

        case tagTimerHourClickSelected:
        m_timer_fling_flags = FLING_HOUR_ENABLED;
        VTLOG0("select hour by click");
        break;
        
        case tagTimerMinuteClickSelected:
        m_timer_fling_flags = FLING_MINUTE_ENABLED;
        VTLOG0("select minute by click");
        break;
    }
}

